#ifndef _H_GEOMETRY_BUILDER_
#define _H_GEOMETRY_BUILDER_

#include <vector>
#include <ostream>
#include <Parsers/IParsingActions.h>
#include <Geometry/SimplexProperty.h>
#include <Geometry/SRS.h>
#include <Geometry/StreamableGeometry.h>

namespace GST {

namespace Geometry {
	
// this file contains a basic geometry
// which inherits from IParsingActions in order to
// parse a SFS/SFSP string into the geometry
	
/**
	*	We need a basic vertex which has x,y,z
	*/
struct Vertex {
	double x;
	double y;
	double z;

	/**
		*	construct a vertex by setting x,y,z. If one of them is omitted it is set to 0.0.
		*	@param a double coordinate for x, defaults to 0.0
		*	@param b double coordinate for y, defaults to 0.0
		*	@param c double coordinate for z, defaults to 0.0
		*/
	Vertex(const double& a=0.0, const double& b=0.0, const double& c=0.0);
};


//-----------------------------------------------------------------------------------------------------------

	
/**
	*	A simple line which is made of two vertices
	*/
struct LineSegment {
	size_t v[2];

	/**
		*	construct a line by passing two vertex indices and store them in the member
		*	@param v1 the index of the first vertex, defaults to 0
		*	@param v2 the index of the second vertex, defaults to 0
		*/
	LineSegment(const size_t& v1=0, const size_t& v2=0);
};


//-----------------------------------------------------------------------------------------------------------


	
/**
	*	A simple triangle which is made of three vertices
	*/
struct Triangle {
	size_t v[3];

	/**
		*	construct a triangle by passing three vertex indices and store them in the member
		*	@param v1 the index of the first vertex, defaults to 0
		*	@param v2 the index of the second vertex, defaults to 0
		*	@param v3 the index of the third vertex, defaults to 0
		*/
	Triangle(const size_t& v1=0, const size_t& v2=0, const size_t& v3=0);
};


//-----------------------------------------------------------------------------------------------------------


	
/**
	*	A simple tetrahedroon which is made of four vertices
	*/
struct Tetra {
	size_t v[4];

	/**
		*	construct a triangle by passing three vertex indices and store them in the member
		*	@param v1 the index of the first vertex, defaults to 0
		*	@param v2 the index of the second vertex, defaults to 0
		*	@param v3 the index of the third vertex, defaults to 0
		*	@param v4 the index of the fourth vertex, defaults to 0
		*/		
	Tetra(const size_t& v1=0, const size_t& v2=0, const size_t& v3=0, const size_t& v4=0);
		
};


//-----------------------------------------------------------------------------------------------------------


/**
  * Handles meta data about a simplex property (property inside a geometry).
  */
class SimplexPropertyDescription
	: public SimplexProperty
{

public:

	SimplexPropertyDescription(const std::string name, PropertyType dataType, unsigned int dimension, PropertyAlignment alignment)
		: name(name), dataType(dataType), dimension(dimension), alignment(alignment)
	{}

	///@name SimplexProperty members
	//@{
	virtual std::string getName() const { return this->name; }
	virtual void setName(const std::string &name) { this->name = name; }
	virtual PropertyType getType() const { return this->dataType; }
	virtual int getDimension() const { return this->dimension; }
	virtual PropertyAlignment getAlignment() const { return this->alignment; }
	//@}

private:
	std::string name;
	PropertyType dataType;
	unsigned int dimension;
	PropertyAlignment alignment;
};


//-----------------------------------------------------------------------------------------------------------


	
// typedef some vectors
typedef std::vector<Vertex> Vertices;
typedef std::vector<LineSegment> LineSegments;
typedef std::vector<Triangle> Triangles;
typedef std::vector<Tetra> Tetrahedrons;
	

//-----------------------------------------------------------------------------------------------------------

/**
	*	\defgroup refGeometryBuilder The Class GeometryBuilder
	*	The class GeometryBuilder makes it easy to construct a description of the geometry for the network communication. It
	*	inherits from StreamableGeometry and thus it can be used by ClientUtils::NetworkInterface to send geometries.
	*
	*
	*	This class also inherits from Parsers::IParsingActions and thus is also can be used from WKT Parser. This makes
	*	the understanding of calling convention more easy. If you know in which order IParsingActions are called by the 
	*	Parser, you know how to construct a geometry description with the help of this class.
	*
	*	A sample creation of a Multipoint geometry with two properties stored on vertex level can look following. Property1
	*	always have one-digit values, property2 has two-digit integer values. Both storing 1 dimensional values:
			\code
			GeometryBuilder gb;
			gb.CreateMultipoint3();
			gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
			gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeInt, 1);

			gb.addPoint( RawPoint3(0,0,0) ); gb.PropAddValue("1"); gb.PropAddValue("10"); 
			gb.addPoint( RawPoint3(0,1,0) ); gb.PropAddValue("2"); gb.PropAddValue("20");
			gb.addPoint( RawPoint3(0,0,1) ); gb.PropAddValue("3"); gb.PropAddValue("30");
			gb.addPoint( RawPoint3(1,1,1) ); gb.PropAddValue("4"); gb.PropAddValue("40");

			std::stringstream output_geometry;
			std::stringstream output_property;
			gb.serializeGeometry(output_geometry);
			gb.serializeSimplexPropertyValues(output_property);
			\endcode

	*	As you see the sequence of creating a property (line 3 and 4) is the same when calling PropAddValue(). (The values 1,2,3,4 belongs to \e property1 and 10,20,30,40 to \e property2 .)
	*
	*	You also can add Property Values in one call with a vector. In meta code it will look like this:
		\code
		gb.addPoint( RawPoint3(0,0,0) ); gb.PropVector( {"1";"10"} ); 
		gb.addPoint( RawPoint3(0,1,0) ); gb.PropVector( {"2";"20"} ); 
		gb.addPoint( RawPoint3(0,0,1) ); gb.PropVector( {"3";"30"} ); 
		gb.addPoint( RawPoint3(1,1,1) ); gb.PropVector( {"4";"40"} ); 
		\endcode

	*	If you have a multidimensional property it will be filled in the same way. If you have a multidimensional property (let's say a dimension of 3) call PropAddVector() 
	*	1 times with a vector with 3 elements (or PropAddValue() 3 times) 
	*	to refer to the next property in sequence.
	*
	*	The Spatial Reference System can be defined by setSRS(). For examples how to construct Spatial Reference systems please consult the class Geometry::SRS.
	*	If no SRS is set, the geometry will be assumed to have no SRS (NoSRS). You can upload this geometry into a class with a SRS. In this case it's assumed that the 
	*	geometry has the same SRS (see NetworkInterface::UploadFeature()).
	*	It is recommended to define the SRS of an object.
	*
	*
	*/

/** 
 *\copydoc refGeometryBuilder
 */
class GST_API_EXPORT GeometryBuilder 
	: public GST::Parsers::IParsingActions
	, public GST::Geometry::StreamableGeometry
{
protected:
	typedef std::vector<SimplexPropertyDescription> SimplexPropertyDescriptionContainer;
	typedef SimplexPropertyDescriptionContainer::iterator SimplexPropertyDescriptionContainerItr;
	typedef SimplexPropertyDescriptionContainer::const_iterator SimplexPropertyDescriptionContainerCItr;

	std::string object_name;
	IGeometry::Color object_color; 
	IGeometry::TransparencyCode object_alpha;
	Geometry::SRSPtr object_srs;
	KeyValueList various_properties;
	GST::Parsers::GridDescription grid_description;

public:
	/**
		*	A bunch of vertices. They are needed for every geometry type.
		*/
	Vertices vertex_container;
protected:
	/**
		*	Some lines. This vector contains only elements if the geometry type
		*	has been set to GeomType_SegmentLine.
		*/
	LineSegments segment_container;
public:
	/**
		*	Some triangles. This vector contains only elements if the geometry type
		*	has been set to GeomType_TriangleNet.
		*/
	Triangles triangle_container;
protected:
	/**
		*	Some tetrahedra. This vector contains only elements if the geometry type
		*	has been set to GeomType_Tetrahedronnet.
		*/
	Tetrahedrons tetra_container;
public:
	/**
		*	Some geometries. This vector contains only elements if the geometry type
		*	has been set to GeomType_Collection.
		*/
	std::vector<GeometryBuilder> collection_container;

	/**
	  * stores the property values that are aligned with the vertices.
	  */
	std::vector<std::string> vertex_property_val_container;
protected:

	/**
	  * stores the property values that are aligned with the cells (eg. segment, triangle or tetrahedron).
	  */
	std::vector<std::string> cell_property_val_container;

	/**
	  * stores the property description in the same order they are created.
	  */
	SimplexPropertyDescriptionContainer property_desc_container;

	///loop helper for addValue and addVector
	struct PropertyLooper
	{
		SimplexPropertyDescriptionContainerItr property_desc_iterator;
		int property_desc_dim_count;
	} property_looper;

protected:
	/**
		*	This enum lists all possible geometry types. The names
		*	are partly borrowed from gOcad.
		*/
	enum geoType {
		GeomType_Point,					///< A Multipoint object
		GeomType_SegmentLine,			///< A Multiline object created segment wise
		GeomType_MultiLine,				///< A Multiline object created linestring wise
		GeomType_TIN,					///< A Triangulated object create triangle wise
		GeomType_TriangleNet,			///< A Triangulated object created by point and index list
		GeomType_Tetrahedronnet,		///< A Tetrahedron object created tretrahedron wise
		GeomType_TetraMultipolygon,		///< A Tetrahedron object created by point and index list
		GeomType_Collection,			///< A Collection of objects above
		GeomType_Grid,					///< A Grid object
		GeomType_unkown					///< A default value. This is not presenting a valid type.
	};
	// make it a member
public:
	geoType type;
		
	/**
		*	basic constructor which only set the geometry type to GeomType_unkown.
		*/
	GeometryBuilder();

	//@name Geometry creation
	//@{
	/**
		*	implementation of IParsingActions::CreateMultipoint3.
		*	This sets the type to geoType::GeomType_Point. If the geometry is a GeomType_Collection
		*	a new geometry is created and CreateMultipoint3 is invoked for it.
		*	The new created geometry will be pushed to the collection_container vector.
		*
		*	Sample Creation
				\code
				GeometryBuilder gb;
				gb.CreateMultipoint3();
				gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
				gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeInt, 1);

				gb.addPoint( RawPoint3(0,0,0) ); gb.PropAddValue("1"); gb.PropAddValue("10"); 
				gb.addPoint( RawPoint3(0,1,0) ); gb.PropAddValue("2"); gb.PropAddValue("20");
				gb.addPoint( RawPoint3(0,0,1) ); gb.PropAddValue("3"); gb.PropAddValue("40");
				gb.addPoint( RawPoint3(1,1,1) ); gb.PropAddValue("4"); gb.PropAddValue("50");

				std::stringstream output_geometry;
				std::stringstream output_property;
				gb.serializeGeometry(output_geometry);
				gb.serializeSimplexPropertyValues(output_property);
				\endcode
		*	@note Mixable call: It's up to you to call the PropAddValue() or PropAddVector() direct after each addPoint(),
		*	or at the end. The only rule is, that order of Add methods refers to the same simplices.
		*
		*	@see IParsingActions::CreateMultipoint3()
		*/
	virtual void CreateMultipoint3();
		
	/**
		*	implementation of IParsingActions::CreateMultiline3.
		*	This sets the type to geoType::GeomType_SegmentLine. If the geometry is a GeomType_Collection
		*	a new geometry is created and CreateMultiline3 is invoked for it.
		*	The new created geometry will be pushed to the collection_container vector.
		*
		*	Sample Creation
				\code
				GeometryBuilder gb;
				gb.CreateMultiline3();
				gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
				gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeInt, 1);

				gb.newSimplex();
				gb.addPoint( RawPoint3(0,0,0) ); gb.PropAddValue("1"); gb.PropAddValue("10");
				gb.addPoint( RawPoint3(0,1,0) ); gb.PropAddValue("2"); gb.PropAddValue("20");
				gb.addPoint( RawPoint3(0,0,1) ); gb.PropAddValue("3"); gb.PropAddValue("30");
				gb.addPoint( RawPoint3(1,1,1) ); gb.PropAddValue("4"); gb.PropAddValue("40");

				gb.newSimplex();
				gb.addPoint( RawPoint3(0,0,0) ); gb.PropAddValue("5"); gb.PropAddValue("50");
				gb.addPoint( RawPoint3(0,2,0) ); gb.PropAddValue("6"); gb.PropAddValue("60");
				gb.addPoint( RawPoint3(0,0,2) ); gb.PropAddValue("7"); gb.PropAddValue("70");
				gb.addPoint( RawPoint3(2,2,2) ); gb.PropAddValue("8"); gb.PropAddValue("80");

				std::stringstream output_geometry;
				std::stringstream output_property;
				gb.serializeGeometry(output_geometry);
				gb.serializeSimplexPropertyValues(output_property);
				\endcode
		*	@note Mixable call: It's up to you to call the PropAddValue() or PropAddVector() direct after each addPoint(),
		*	or at the end. The only rule is, that order of Add methods refers to the same simplices.
		*
		*	@see IParsingActions::CreateMultiline3()
		*/
	virtual void CreateMultiline3();

	/**
		*	2nd style creation of a Multiline object. The serializeGeometry() method will output the same, 
		*	but the process of creation differs.
		*	This sets the type to geoType::GeomType_SegmentLine. If the geometry is a GeomType_Collection
		*	a new geometry is created and CreateMultiline3 is invoked for it.
		*	The new created geometry will be pushed to the collection_container vector.
		*
		*	Sample creation:
				\code
				GeometryBuilder gb;
				gb.CreateSegmentLine3();
				gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
				gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeInt, 1);

				gb.addPoint( RawPoint3(0,0,0) ); gb.PropAddValue("1"); gb.PropAddValue("10");
				gb.addPoint( RawPoint3(0,1,0) ); gb.PropAddValue("2"); gb.PropAddValue("20");
				gb.newSimplex(); //Part here has the meaning of a segement (v1-v2)
				gb.addPoint( RawPoint3(0,0,1) ); gb.PropAddValue("3"); gb.PropAddValue("30");
				gb.newSimplex();
				gb.addPoint( RawPoint3(1,1,1) ); gb.PropAddValue("4"); gb.PropAddValue("40");
				gb.newSimplex();

				//two time addPoint indicates a new part
				gb.addPoint( RawPoint3(0,0,0) ); gb.PropAddValue("5"); gb.PropAddValue("50");
				gb.addPoint( RawPoint3(0,2,0) ); gb.PropAddValue("6"); gb.PropAddValue("60");
				gb.newSimplex();
				gb.addPoint( RawPoint3(0,0,2) ); gb.PropAddValue("7"); gb.PropAddValue("70");
				gb.newSimplex();
				gb.addPoint( RawPoint3(2,2,2) ); gb.PropAddValue("8"); gb.PropAddValue("80");
				gb.newSimplex();

				std::stringstream output_geometry;
				std::stringstream output_property;
				gb.serializeGeometry(output_geometry);
				gb.serializeSimplexPropertyValues(output_property);
				\endcode
		*	@note Mixable call: It's up to you to call the PropAddValue() or PropAddVector() direct after each addPoint(),
		*	or at the end. The only rule is, that order of Add methods refers to the same simplices.
		*/
	virtual void CreateSegmentLine3();
		
	/**
		*	implementation of IParsingActions::CreateTIN3. 2nd style creation of a TriangleNet3 object. The serializeGeometry() method will output the same, 
		*	but the process of creation differs. 
		*	This sets the type to geoType::GeomType_TriangleNet. If the geometry is a GeomType_Collection
		*	a new geometry is created and CreateTIN3 is invoked for it.
		*	The new created geometry will be pushed to the collection_container vector.
		*
		*	Sample creation:
				\code
				GeometryBuilder gb;
				gb.CreateTIN3();
				gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
				gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeInt, 1);

				gb.newSimplex();
				gb.addPoint( RawPoint3( 0.5 ,   0 , 1) ); //index: 0
				gb.PropAddValue("1"); gb.PropAddValue("10");
				gb.addPoint( RawPoint3(   0 ,   1 , 0) ); //index: 1
				gb.PropAddValue("2"); gb.PropAddValue("20");
				gb.addPoint( RawPoint3(   1 ,   1 , 0) ); //index: 2
				gb.PropAddValue("3"); gb.PropAddValue("30");
				gb.newSimplex();
				gb.addPoint( RawPoint3(   0 ,   1 , 0) ); //index: 1
				gb.addPoint( RawPoint3(   1 ,   1 , 0) ); //index: 2
				gb.addPoint( RawPoint3(   0 ,   2 , 0) ); //index: 3
				gb.PropAddValue("4"); gb.PropAddValue("40");
				gb.newSimplex();
				gb.addPoint( RawPoint3(   1 ,   1 , 0) ); //index: 2
				gb.addPoint( RawPoint3(   0 ,   2 , 0) ); //index: 3
				gb.addPoint( RawPoint3(   2 ,   2 , 0) ); //index: 4
				gb.PropAddValue("5"); gb.PropAddValue("50");
				\endcode
		*	@note Mixable call: It's up to you to call the PropAddValue() or PropAddVector() direct after each addPoint(),
		*	or at the end. The only rule is, that order of Add methods refers to the same simplices.
		*
		*	@see IParsingActions::CreateTIN3()	  
		*/
	virtual void CreateTIN3();	
	
	/**
		*	implementation of IParsingActions::CreateTriangleNet3.
		*	This sets the type to geoType::GeomType_TriangleNet. If the geometry is a GeomType_Collection
		*	a new geometry is created and CreateTriangleNet3 is invoked for it.
		*	The new created geometry will be pushed to the collection_container vector.
		*
		*	Sample creation:
				\code
				GeometryBuilder gb;
				gb.CreateTriangleNet3();
				gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
				gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeInt, 1);

				gb.addPoint( RawPoint3( 0.5 ,   0 , 1) ); //index: 0
				gb.PropAddValue("1"); gb.PropAddValue("10");
				gb.addPoint( RawPoint3(   0 ,   1 , 0) ); //index: 1
				gb.PropAddValue("2"); gb.PropAddValue("20");
				gb.addPoint( RawPoint3(   1 ,   1 , 0) ); //index: 2
				gb.PropAddValue("3"); gb.PropAddValue("30");
				gb.addPoint( RawPoint3(   0 ,   2 , 0) ); //index: 3
				gb.PropAddValue("4"); gb.PropAddValue("40");
				gb.addPoint( RawPoint3(   2 ,   2 , 0) ); //index: 4
				gb.PropAddValue("5"); gb.PropAddValue("50");
				//...
				gb.addTriangle( IdxTriangle(0 ,1 ,2) ); 
				gb.addTriangle( IdxTriangle(1 ,2 ,3) ); 
				gb.addTriangle( IdxTriangle(2 ,3, 4) );


				std::stringstream output_geometry;
				std::stringstream output_property;
				gb.serializeGeometry(output_geometry);
				gb.serializeSimplexPropertyValues(output_property);
				\endcode
		*	@note Mixable call: It's up to you to call the PropAddValue() or PropAddVector() direct after each addPoint(),
		*	or at the end. The only rule is, that order of Add methods refers to the same simplices.
		*
		*	@see IParsingActions::CreateTriangleNet3()		  
		*/
	virtual void CreateTriangleNet3();

	/**
		*	implementation of IParsingActions::CreateMultiPolygon3.	 
		*	2nd style creation of a Tetrahedon3 object. The serializeGeometry() method will output the same, 
		*	but the process of creation differs. 
		*	This sets the type to geoType::GeomType_Tetrahedronnet. If the geometry is a GeomType_Collection
		*	a new geometry is created and CreateMultiPolygon3 is invoked for it.
		*	The new created geometry will be pushed to the collection_container vector.
		*
		*	Sample creation:
				\code
				GeometryBuilder gb;
				gb.CreateMultiPolygon3();
				gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
				gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeInt, 1);

				gb.newSimplex();
				gb.addPoint( RawPoint3(   0 ,   0 , 0) ); //index: 0
				gb.PropAddValue("1"); gb.PropAddValue("10");
				gb.addPoint( RawPoint3(   1 ,   0 , 0) ); //index: 1
				gb.PropAddValue("2"); gb.PropAddValue("20");
				gb.addPoint( RawPoint3(   0 ,   1 , 0) ); //index: 2
				gb.PropAddValue("3"); gb.PropAddValue("30");
				gb.addPoint( RawPoint3( 0.5 , 0.5 , 1) ); //index: 4
				gb.PropAddValue("4"); gb.PropAddValue("40");
				gb.newSimplex();
				gb.addPoint( RawPoint3(   1 ,   0 , 0) ); //index: 1
				gb.PropAddValue("5"); gb.PropAddValue("50");
				gb.addPoint( RawPoint3(   0 ,   1 , 0) ); //index: 2
				gb.PropAddValue("6"); gb.PropAddValue("60");
				gb.addPoint( RawPoint3(   1 ,   1 , 0) ); //index: 3
				gb.PropAddValue("7"); gb.PropAddValue("70");
				gb.addPoint( RawPoint3( 0.5 , 0.5 , 1) ); //index: 4
				gb.PropAddValue("8"); gb.PropAddValue("80");
				\endcode
		*	@note Mixable call: It's up to you to call the PropAddValue() or PropAddVector() direct after each addPoint(),
		*	or at the end. The only rule is, that order of Add methods refers to the same simplices.
		*
		*	@see IParsingActions::CreateMultiPolygon3()	   	  
		*/
	virtual void CreateMultiPolygon3();

	/**
		*	implementation of IParsingActions::CreateTetrahedon3.
		*	This sets the type to geoType::GeomType_Tetrahedronnet. If the geometry is a GeomType_Collection
		*	a new geometry is created and CreateTetrahedon3 is invoked for it.
		*	The new created geometry will be pushed to the collection_container vector.
		*
		*	Sample creation:
				\code
				GeometryBuilder gb;
				gb.CreateTetrahedon3();
				gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
				gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeInt, 1);

				gb.addPoint( RawPoint3(   0 ,   0 , 0) ); //index: 0
				gb.PropAddValue("1"); gb.PropAddValue("10");
				gb.addPoint( RawPoint3(   1 ,   0 , 0) ); //index: 1
				gb.PropAddValue("2"); gb.PropAddValue("20");
				gb.addPoint( RawPoint3(   0 ,   1 , 0) ); //index: 2
				gb.PropAddValue("3"); gb.PropAddValue("30");
				gb.addPoint( RawPoint3(   1 ,   1 , 0) ); //index: 3
				gb.PropAddValue("4"); gb.PropAddValue("40");
				gb.addPoint( RawPoint3( 0.5 , 0.5 , 1) ); //index: 4
				gb.PropAddValue("5"); gb.PropAddValue("50");
				//...
				gb.addTetrahedron( IdxTetrahedron(0 ,1 ,2, 4) ); 
				gb.addTetrahedron( IdxTetrahedron(1 ,2, 3, 4) ); 

				std::stringstream output_geometry;
				std::stringstream output_property;
				gb.serializeGeometry(output_geometry);
				gb.serializeSimplexPropertyValues(output_property);
				\endcode		
		*	@note Mixable call: It's up to you to call the PropAddValue() or PropAddVector() direct after each addPoint(),
		*	or at the end. The only rule is, that order of Add methods refers to the same simplices.
		*
		*	@see IParsingActions::CreateTetrahedon3()  	  
		*/
	virtual void CreateTetrahedon3();

	/**
	*	implementation of IParsingActions::CreateGrid3.
	*	This sets the type to geoType::GeomType_Grid. If the geometry is a GeomType_Collection
	*	a new geometry is created and CreateGrid3 is invoked for it.
	*	The new created geometry will be pushed to the collection_container vector.
	*
	*	Sample creation:
			\code
			GeometryBuilder gb;
			
			GridDescription grid_desc;
			grid_desc.setPosition(RawPoint3(4400, 120.55, 312.73));
			grid_desc.setSize(10,10,10);
			grid_desc.setOrientation(RawPoint3(20,0,0), RawPoint3(0,13,0), RawPoint3(0,0,10));

			gb.CreateGrid3(grid_desc);
			gb.set_srs(srs)
			gb.set_name(new_feature_name)
			
			gb.CreateVertexProperty("property1", SimplexProperty::PropertyType::TypeInt, 1);
			gb.CreateVertexProperty("property2", SimplexProperty::PropertyType::TypeText, 1);

			// add value to property1, then add property to property2
			gb.PropAddValue("1"); gb.PropAddValue("10");
			// repeat this until all values (in this case: 10*10*10 = 1000, see "setSize()") are 
			// added for both properties
			gb.PropAddValue("2"); gb.PropAddValue("20");
			gb.PropAddValue("3"); gb.PropAddValue("30");
			gb.PropAddValue("4"); gb.PropAddValue("40");
			gb.PropAddValue("5"); gb.PropAddValue("50");
			gb.PropAddValue("6"); gb.PropAddValue("60");
			gb.PropAddValue("7"); gb.PropAddValue("70");
			gb.PropAddValue("8"); gb.PropAddValue("80");
			//...
			//...
			gb.PropAddValue("998"); gb.PropAddValue("9980");
			gb.PropAddValue("999"); gb.PropAddValue("9990");
			gb.PropAddValue("1000"); gb.PropAddValue("10000");
			
			std::stringstream output_geometry;
			gb.serializeGeometry(output_geometry);
	\endcode
	*/
	virtual void CreateGrid3(const GST::Parsers::GridDescription &grid_description);
		
	/**
		*	implementation of IParsingActions::CreateCollection.
		*	This sets the type to geoType::GeomType_Collection. If the geometry is a GeomType_Collection
		*	a new geometry is created and CreateCollection is invoked for it.
		*	The new created geometry will be pushed to the collection_container vector.
		*
		*	Sample creation:
				\code
				GeometryBuilder gb;
				gb.CreateCollection();
				gb.CreateTriangleNet3();
				//...
				gb.CreateTriangleNet3();
				//...
				gb.CreateMultiline3();
				\endcode
		*	@note Mixable call: It's up to you to call the PropAddValue() or PropAddVector() direct after each addPoint(),
		*	or at the end. The only rule is, that order of Add methods refers to the same simplices.
		*
		*	@see IParsingActions::CreateCollection()	 	  
		*/
	virtual void CreateCollection();
		
	/**
		*	This function is invoked by the parse everytime a part has been finished.
		*	Thus depending on geoType a line, triangle or tretrahedron is created
		*	with the last 2,3,4 indices of pushed back vertices. For a point set
		*	nothing will be done here. For a collection of geometries the newPart method
		*	will be invoked for the last geometry in the vector collection_container.
		*	@see IParsingActions::newSimplex()
		*/
	virtual void newSimplex();
	
	/**
	 *	This function is invoked by the parse everytime a part has been finished.
	 *	Thus depending on geoType a line, triangle or tretrahedron is created
	 *	with the last 2,3,4 indices of pushed back vertices. For a point set
	 *	nothing will be done here. For a collection of geometries the newPart method
	 *	will be invoked for the last geometry in the vector collection_container.
	 *	@see IParsingActions::newSimplex()
	 */
	virtual void newPart(bool oldStyle=true){if (oldStyle) this->newSimplex();}
		
	/**
		*	Adds a raw point to the geomtetry. For a collection the addPoint method is
		*	invoked for the last element in vector collection_container.
		*	@param d is a structure containing x,y,z
		*	@see IParsingActions::addPoint()
		*/
	virtual void addPoint(const GST::Parsers::RawPoint3& d);
		
	/**
		*	Adds a triangle to the geometry. For a collection the addTriangle method is
		*	invoked for the last element in vector collection_container.
		*	@param t is a structure containing v1,v2,v3
		*	@see IParsingActions::addTriangle()
		*/
	virtual void addTriangle(const GST::Parsers::IdxTriangle& t);
		
	/**
		*	Adds a tetrahedron to the geometry. For a collection the addTetrahedron method is
		*	invoked for the last element in vector collection_container.
		*	@param t is a structure containing v1,v2,v3,v4
		*	@see IParsingActions::addTetrahedron()
		*/
	virtual void addTetrahedron(const GST::Parsers::IdxTetrahedron& t);
	//@}

	///@name Property creation
	//@{
	/**
	  *		Invokes a new property aligned to the cell of the object. What a cell is depends of the type of
	  *		of the object. E.g. the cells for a Multiline are the segment, for a TIN the triangles and for
	  *		a Tetrahedronnetwork the tetrahedron. Just for Multipoint objects cell are the vertices too.
	  *
	  *		The sequence of creating a property is the same sequence when calling PropAddValue() or PropAddVector().
	  */
	virtual int CreateCellProperty(const std::string & name, const Geometry::SimplexProperty::PropertyType & PropertyType, const unsigned int & dims);

	/**
	  *		Invoces a new property aligned to the vertices of the object. 
	  *
	  *		The sequence of creating a property is the same sequence when calling PropAddValue() or PropAddVector().
	  */
	virtual int CreateVertexProperty(const std::string & name, const GST::Geometry::SimplexProperty::PropertyType & PropertyType, const unsigned int & dims);

	/**
	  *		Add a property value to the simplex (cell or vertex, depends on the type of property creation).
	  *
	  *		The sequence a value/vector refers to which property depends on the creation sequence of the properties. (See samples of creation above.)
	  *		If you have a multidimensional property (let's say a dimsion of 3) call PropAddValue() 3 times (or PropAddVector() 1 time with a vector with 3 elements) 
	  *		to refer to the next property in sequence.
	  *
	  *		@see CreateMultipoint3()
	  */
	virtual void PropAddValue(const std::string& value);

	/**
	  *		Add a set of property values to the simplex (cell or vertex, depends on the type of property creation).
	  *
	  *		The sequence a value/vector refers to which property depends on the creation sequence of the properties. (See samples of creation above.)
	  *		If you have a multidimensional property (let's say a dimsion of 3) call PropAddVector() 1 times with a vector with 3 elements (or PropAddValue() 3 times) 
	  *		to refer to the next property in sequence.
	  *
	  *		@see CreateMultipoint3()
	  */
	virtual void PropAddVector(const std::vector<std::string>& vector);
	//@}

	///@name Meta creation
	//@{
	/**
	  *		Set the Spatial Refence System for the added coordinates by the AddPoint() method.
	  */
	virtual void setSRS(Geometry::SRSPtr srs);

	/**
	  *		Set object transparency. 0..1 -> solid..transparent 
	  */
	virtual void SetTransparency(const IGeometry::TransparencyCode& alpha);

	/**
	  *		Set object color. Each channel: 0..1 -> zero..full (e.g. {0.8 0.8 0.8} is light grey)
	  */
	virtual void SetColor(const IGeometry::Color& color);

	/**
	  *		Sets the object name
	  */
	virtual void SetName(const std::string & name);

	/**
	  *		Sets a custom object property
	  */
	virtual void SetCustomProperty(const std::string & name, const std::string & value);

	virtual void SetCRS(const std::string& crs);

	virtual std::vector<SimplexPropertyDescription> getPropertyDescriptions() const;
	//@}

	///@name StreamableGeometry members
	//@{
	/**
	  *		Implementation of StreamableGeoemtry
	  */
	virtual bool serializeGeometry(std::ostream & os) const;

	/**
	  *		Implementation of StreamableGeoemtry
	  */
	virtual bool serializeSimplexPropertyDescription(std::ostream & os)	const;

	/**
	  *		Implementation of StreamableGeoemtry
	  */
	virtual bool serializeSimplexPropertyValues(std::ostream & os) const;

	/**
	  *		Implementation of StreamableGeoemtry
	  */
	virtual Geometry::SRSPtr GetSRS() const;

	/**
	  *		Implementation of StreamableGeoemtry
	  */
	virtual IGeometry::TransparencyCode GetTransparency() const;

	/**
	  *		Implementation of StreamableGeoemtry
	  */
	virtual IGeometry::Color GetColor() const;

	/**
	  *		Implementation of StreamableGeoemtry
	  */
	virtual std::string GetName() const;
	
	/**
	  *		Implementation of StreamableGeoemtry
	  */
	virtual KeyValueListPtr GetVariousProperties() const;
	//@}

	/**
		*	The following function are implemented without any function in order
		*	to be able to instantiate an object of the Geometry class. For more
		*	information refer to IParsingActions.
		*	@see IParsingActions
		*/
	///@name not implemented with function
	//@{
	virtual void GeometryParsingFinished();		
	virtual void PropertyParsingFinished();
	virtual void PropNextObject();		   
	virtual boost::ptr_list<IGeometry>* getGeometries();
	virtual void clearGeometries();
	virtual void clear();		
	virtual void NewObject(const std::streampos &,const std::streampos &) {}
	//@}

private:
	///@name private helpers
	//@{
	bool serializeGeometrySFSP(std::ostream & os) const;
	bool serializeGeometryISATIS(std::ostream & os) const;
	void writeCoordinateMultipoint(std::ostream & os) const;
	void writeCoordinateLineString(std::ostream & os) const;
	void writeVertex(const size_t & pos, std::ostream & os) const;
	void writeTriangleList(std::ostream & os) const;
	void writeTetraList(std::ostream & os) const;
	//@}

};
		
} //of namespace Geometry
} //of namespace GST

#endif //_H_GEOMETRY_BUILDER_